package sample.util;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;
import sample.SceneBuilder;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayDeque;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

/**

 * @name      :DrawPane

 * @Description: the drawPane for drawing and the EasterEggs

*/
public class DrawPane extends Pane {
    final ArrayDeque<Line> lines;
    AtomicInteger lx,ly;
    Color nextColor;
    double strokeWidth;
    AtomicInteger keys;
    final static double DEFAULT_STROKE_WIDTH=1.0;
    public DrawPane(){this(300,300);}
    public DrawPane(int minHeight,int minWidth){
        // Init part
        super();
        this.setMinSize(minHeight,minWidth);
        this.lines=new ArrayDeque<>();
        lx=new AtomicInteger(-1);
        ly=new AtomicInteger(-1);
        keys=new AtomicInteger();
        this.nextColor=Color.BLACK;
        this.strokeWidth=DEFAULT_STROKE_WIDTH;
//        this.strokeWidth=
        //todo draw func
        this.setOnMouseDragged(e->{
            this.addLine(e.getX(),e.getY());
            this.keys.set(0);
//            System.out.println(" SceneX : "+e.getScreenX()+" SceneY : "+e.getSceneY());
//            System.out.println(" X : "+e.getX()+" Y : "+e.getY());
        });
        this.setOnMouseReleased(e-> this.reset());
    }
    private void set(double dx,double dy){
        this.lx.set((int)dx);
        this.ly.set((int)dy);
    }
    private void set(double dx,double dy,int val){
        this.set(dx,dy);
        this.keys.set(val);
    }
    private void reset(){
        this.set(-1,-1,0);
    }
    @Deprecated
    public static Pane BlankPane(int minHeight, int minWidth){
        Pane p=new Pane();
        p.setMinHeight(minHeight);
        p.setMinWidth(minWidth);
        return p;
    }
    public DrawPane addLine(double x1,double y1,double x2,double y2){
        Line line=new Line(x1,y1,x2,y2);
        lines.addLast(line);
        this.getChildren().add(line);
        return this;
    }
    public DrawPane addLine(double x,double y){
        if(this.lx.get()!=-1){
            Line line=new Line(this.lx.get(),this.ly.get(),x,y);
            lines.addLast(Ctl.LineProperty(line,this.nextColor,this.strokeWidth));
            this.getChildren().add(line);
        }
        this.set(x,y);
        return this;
    }
    public void save(){
        lines.clear();
    }
    public void clear(){
        lines.clear();
        this.getChildren().clear();
    }
    public void undo(){
        while(lines.size()!=0)
            this.getChildren().remove(lines.pollLast());
    }
    public void setStrokeWidth(double strokeWidth) {
        this.strokeWidth = strokeWidth;
    }
    public double getStrokeWidth() {
        return strokeWidth;
    }

    public Color getNextColor() {
        return nextColor;
    }
    public void setNextColor(Color nextColor) {
        this.nextColor = nextColor;
    }


    /**

     * @name      :RGBMenuItem

     * @param     :[dp]

     * @return    :void

     * @Description: implement the RGB Button and finish the work of the color change

    */
    // Function implement
    // And some static methods
    // todo RGBMenuItem
    public static void RGBMenuItem(DrawPane dp){
        // todo
        // Get the stage
        Stage stage=new Stage();
        stage.setTitle("RGB Input");
        ThreeRowGetPane trp=new ThreeRowGetPane(
                new Text("R : "),new TextField(),
                new Text("G : "),new TextField(),
                new Text("B : "),new TextField()
        );
        stage.setScene(new Scene(trp));

        // Set background color
        SplitPane sp=(SplitPane)trp.getChildren().get(0);
        sp.getItems().get(0).setStyle("-fx-background-color: red");
        sp.getItems().get(1).setStyle("-fx-background-color: green");
        sp.getItems().get(2).setStyle("-fx-background-color: blue");

        trp.addButtonEvent(e->{
            dp.setNextColor(ThreeRowGetPane.GetColorFromPane(trp));
            stage.close();
        });
        stage.show();
        /*
         * 弹出窗口
         * 窗口填写 rgb 数值
         * 设置点击文字刷新预览
         * 点击 Enter 返回
         * */
    }
    public static void MenuStrokeWidth(Menu m, DrawPane dp){
        // Three increasing value 1->2->4
        Ctl.Paint_Menu_Three_Type_Set(m);
        MenuItemStrokeAction(m.getItems().get(0),1,dp);
        MenuItemStrokeAction(m.getItems().get(1),2,dp);
        MenuItemStrokeAction(m.getItems().get(2),4,dp);
        m.getItems().get(3).setOnAction(e-> new Alert("No time to implement this",5).show());
    }
    private static void MenuItemStrokeAction(MenuItem mi, int size, DrawPane dp){
        mi.setOnAction(e-> dp.setStrokeWidth(size));
    }
    public static void MenuColorAction(Menu m,int endOfColor,DrawPane dp){
        String[]colors={"Black","Red","Green","Yellow"};
        for (int i = 0; i < endOfColor; i++) {
            MenuItemColorAction(m.getItems().get(i),Color.valueOf(colors[i].toUpperCase()),dp);
        }
        // ... func
        m.getItems().get(endOfColor).setOnAction(e-> RGBMenuItem(dp));
    }
    private static void MenuItemColorAction(MenuItem mi,Color color,DrawPane dp){
        mi.setOnAction(e-> dp.setNextColor(color));
    }
    public void egg(){
        // todo make the EasterEgg
        new Alert("Heart",15, SceneBuilder.HeartBoard()).show();
    }
    public void setOnclickCroatian(MediaPlayer music){
        this.setOnKeyPressed(e->{
            switch(e.getCode()){
                case DIGIT7,NUMPAD7 ->{
                    if(keys.get()==0)
                        keys.incrementAndGet();
                    else keys.set(0);
                }
                case DIGIT1,NUMPAD1 ->{
                    if(keys.get()==1)
                        keys.incrementAndGet();
                    else keys.set(0);
                }
                case DIGIT6,NUMPAD6 ->{
                    if(keys.get()==2){
                        DrawPane.MusicPlayerTimes(15,music);
                    }
                    keys.set(0);
                }
                default -> keys.set(0);
            }
        });
    }
    /**

     * @name      :Croatian

     * @param     :[cut]

     * @return    :javafx.scene.media.MediaPlayer

     * @Description: player of Croatian
     * the one of the EasterEgg I like most

    */
    public static MediaPlayer Croatian(boolean cut){
        String CroatianPath;
        if(cut)CroatianPath="src/audio/CroatianCut.mp3";
        else CroatianPath="src/audio/Croatian.mp3";
        File Croatian=new File(CroatianPath);
        Media media= null;
        try {
            media = new Media(Croatian.toURI().toURL().toString());
        } catch (MalformedURLException e) {
            //todo with exception
//            Ctl.MessageBox()
        }
        assert media != null;
        MediaPlayer music=new MediaPlayer(media);
        music.setVolume(50);
        return music;
    }
    public static void CroatianRhapsody(int times){
        MusicPlayerTimes(times,Croatian(false));
    }
    public static void MusicPlayerTimes(int times,MediaPlayer music){
        AtomicBoolean once=new AtomicBoolean(false);
        Timeline timeline=new Timeline(new KeyFrame(Duration.millis(times*1000), e->{
            if(!once.get()){
                music.play();
                once.set(true);
            }
            else music.stop();
        }));
        timeline.setCycleCount(2);
        timeline.play();

    }
}
